home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
ICON
/
ICONV8
/
Source
/
Common
/
C
/
Dirscan
next >
Wrap
Text File
|
1991-05-24
|
5KB
|
217 lines
/* C.Dirscan: Get filenames for a wildcarded value */
/* Use as:
*
* for (file = dirscan(wild); file; file = dirscan(0))
* ...
*
* Specifying an argument other than 0 restarts the scan with the
* new wildcard value.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kernel.h"
#include "swis.h"
/* Constants. The function assumes that a directory can hold no more than
* MAX_DIR entries, and a filename can be no longer than NAME_LEN characters.
* It also assumes that OS_GBPB 9 will only ever fail to return all possible
* filenames on the first call if the supplied buffer becomes full. In this
* case, dirscan() will ignore any omitted entries. This behaviour is not
* ideal, but gains significantly in efficiency. (The given buffer size
* should be easily enough for all normal cases).
*/
#define MAX_DIR 255
#define NAME_LEN 10
#define BUFFER_SIZE (MAX_DIR * (NAME_LEN + 1))
char *dirscan (const char *f)
{
int len;
int dot_stripped = 0;
const char *file;
_kernel_swi_regs regs;
static char *ptr = NULL;
static int num_left = 0;
static char *buffer = NULL;
static char *name;
static char res[255];
if (f && *f)
{
/* Delete any old buffer */
if (buffer)
{
free (buffer);
buffer = NULL;
}
/* Try for a directory prefix */
file = strrchr (f, '.');
/* If not, try for a filing system prefix */
if (file == NULL)
{
if (*f == '-')
file = strchr (f + 1, '-');
else
file = strchr (f, ':');
}
if (file == NULL)
{
/* We have a simple file name, with no directory. So
* we set name to point to the place to store the
* file name (ie, res), and we temporarily set res
* to hold the directory name (ie, ""). We also set
* file to the file name f.
*/
name = res;
file = f;
name[0] = '\0';
}
else
{
/* More work to do. Set res up with the directory,
* as above, and point name to the place to put the
* file name(s). And set file to the file name.
*/
len = file - f + 1;
/* Do not allow file names over 255 characters
* (ie, 245 for the directory, and 10 for the
* base name).
*/
if (len > 245)
return 0;
/* Build the start of the file name to be returned */
strncpy (res, f, len);
name = &res[len];
/* Temporarily, put the name of the directory to scan
* into res. At the moment, res holds "dir." or "FS:"
* without a NULL terminator. If the former, we must
* temporarily remove the dot and add a NULL, but if
* the latter, we must add the current directory
* name "@".
*/
if (*file == '.')
{
dot_stripped = name[-1];
name[-1] = '\0';
}
else
{
name[0] = '@';
name[1] = '\0';
}
/* Now, set file to the base file name */
++file;
}
/* Is the file name wildcarded? */
if (!strchr (file, '*') && !strchr (file, '#'))
{
/* If not, we return the name we were handed,
* and remember not to return any more later.
*/
/* First restore the proper prefix */
if (dot_stripped)
name[-1] = dot_stripped;
strcpy (name, file);
num_left = 0;
return res;
}
else
{
/* OK, this is the big one. We set up a buffer, and
* read all the names from the selected directory
* which match the pattern into it.
*/
buffer = malloc (BUFFER_SIZE) ;
if (buffer == NULL)
return 0;
regs.r[0] = 9;
regs.r[1] = (int) res;
regs.r[2] = (int) buffer;
regs.r[3] = BUFFER_SIZE;
regs.r[4] = 0;
regs.r[5] = BUFFER_SIZE;
regs.r[6] = (int) file;
if (_kernel_swi (OS_GBPB, ®s, ®s))
return 0;
/* Now restore the proper prefix */
if (dot_stripped)
name[-1] = dot_stripped;
/* If there were no entries to find, say so */
if (regs.r[3] == 0)
{
num_left = 0;
free (buffer);
buffer = NULL;
return 0;
}
/* Remember how many more to return and set ptr
* ready to return the next one.
*/
num_left = regs.r[3] - 1;
ptr = buffer + strlen (buffer) + 1;
/* Return the first one */
strcpy (name, buffer);
return res;
}
}
/* If we've run out of names to return, free the buffer and stop */
if (num_left == 0)
{
if (buffer)
{
free (buffer);
buffer = NULL;
}
return 0;
}
/* Return the next entry in the buffer, and move on in the buffer */
strcpy (name, ptr);
ptr += strlen(ptr) + 1;
--num_left;
return res;
}
#ifdef TEST
#include <stdio.h>
int main (int argc, char *argv[])
{
char *name;
while (--argc > 0)
{
printf("Scanning %s\n", *++argv);
for (name = dirscan(*argv); name; name = dirscan(0))
printf("%s\n", name);
}
return 0;
}
#endif